package com.studentSystemData;

import java.util.ArrayList;
import java.util.Random;
import java.util.Scanner;

public class userLogin {
    public static void main(String[] args) {

        System.out.println("欢迎来到学生管理系统：");

        Scanner sc = new Scanner(System.in);

        ArrayList<User> list = new ArrayList<User>();


        do{
            System.out.println("请选择操作1登录 2注册 3忘记密码 4关闭");
            System.out.println("请输入要执行的选项：");

            int choose = sc.nextInt();
            switch (choose) {
                case 1 -> login(list);
                case 2 -> register(list);
                case 3 -> forgetPassword(list);
                case 4 -> System.exit(0);//关闭虚拟机jvm退出程序
                default -> System.out.println("没有这个选项： ");
            }
        }while (true);
    }
    //1注册用户名以及密码
    public static void register(ArrayList<User> list) {

        //1键盘录入用户名：
        //判断用户名是否唯一：并且长度在3~15之间：
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名： ");
        String username = getUsername(list);
        System.out.println(username);
        if(!username.startsWith("用户名不符合要求")){
            System.out.println("用户名输入成功！");
        }

        //2键盘录入密码判断密码的合法性
        String password = "";
        do{
            System.out.println("请输入第一次密码：");
            password = sc.next();
            System.out.println("请再确认一次密码：");
            String passwordAgain = sc.next();

            boolean flag = rightPassword(password, passwordAgain);
            if (flag) {
                System.out.println("输入密码成功：");
                break;
            }
            else {
                System.out.println("两次密码不一致，请重新输入：");
            }
        }while (true);

        //3键盘录入身份证号码：
        String idCard = "";
        do{
            System.out.println("请输入身份证号码：");
            String insert = sc.next();
            idCard = rightIdCard(list, insert);
            if(!idCard.startsWith("身份证不满足要求")){
                System.out.println("身份证输入正确：");
                break;
            }
        }while(true);

        //3手机号验证
        String phoneNumber = "";
        do{
            System.out.println("请输入手机号：");
            String number = sc.next();
            phoneNumber = rightPhoneNumber(list, number);
            if(!phoneNumber.startsWith("手机号输入不合法")){
                System.out.println("手机号输入成功！");
                break;
            }
        }while(true);
        User u  = new User(username,password,idCard,phoneNumber);
        list.add(u);
    }
    //2登录
    public static void login(ArrayList<User> list) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名：");
        String username = sc.next();

        //先获取用户名对应的索引：
        int userIndex = getId(list,username);
        if(userIndex == -1){
            System.out.println("用户名未注册，请先注册");
            return;
        }
        System.out.println("用户名正确");
        //传入用户索引和密码
        passWordAndCode(list,userIndex);



    }
    //3忘记密码，找回密码修改
    public static void forgetPassword(ArrayList<User> list) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入用户名：");
        String username = sc.next();

        //先获取用户名对应的索引：
        int userIndex = getId(list,username);
        if(userIndex == -1){
            System.out.println("用户名未注册，请先注册");
            return;
        }
        System.out.println("用户名正确：");

        System.out.println("请输入身份证号码：");
        String idCard = sc.next();
        System.out.println("<请输入密码：");
        String password = sc.next();

        if(idCard.equals(list.get(userIndex).getPersonid())&&
        password.equals(list.get(userIndex).getPassword())){
            System.out.println("账号信息匹配成功：");
            System.out.println("请输入你要修改的密码：");
            String changePassword = sc.next();
            list.get(userIndex).setPassword(changePassword);
            System.out.println("修改成功！");
        }
        else {
            System.out.println("账号信息不一致，修改失败");
        }


    }




    //构造一个方法，判断密码和验证码是否正确有3次机会：
    public static void passWordAndCode(ArrayList<User> list, int Index) {
        Scanner sc = new Scanner(System.in);
        //记录试错机会
        int usercount = 3;//密码独立计数
        while(usercount > 0){
            System.out.println("请输入密码：");
            String passWord = sc.next();
            //验证当前用户的密码：
            if(passWord.equals(list.get(Index).getPassword())){
                System.out.println("密码正确：");
                break;
            }
            else{
                usercount--;
                System.out.println("密码错误，还有"+usercount+"次机会");
                if(usercount == 0){
                    System.out.println("密码输入错误过多，返回程序：");
                    return;
                }
            }
        }

        //生成独立计数
        int verifycount = 3;
        while(verifycount > 0){
            //生成5位随机验证码：
            String temp = randomCode(list);

            //键盘录入验证码：
            System.out.println("请输入验证码:" + temp);
            String authCode = sc.next();

            if(temp.equals(authCode)){
                System.out.println("验证成功：");
                return;
            }
            else {
                verifycount--;
                System.out.println("输入错误，你还有"+verifycount+"次机会");

                if(verifycount == 0){
                    System.out.println("验证码输入错误次数过多，返回程序");
                    return;
                }
            }
        }


    }
    //构造一个获取随机验证码的方法
    public static String randomCode(ArrayList<User> list) {
        //生成5位验证码：大小写字母都可以，4位字母，1位数字
        //数字的位置可以随机出现
        Random r = new Random();
        //1:先设置一个数组能存'a'到'Z'
        char[]arr = {'A', 'B', 'C', 'D', 'E', 'F',
                'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N',
                'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V',
                'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
                'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
                'm', 'n', 'o', 'p', 'q', 'r', 's', 't',
                'u', 'v', 'w', 'x', 'y', 'z'};
        //获取4个打乱的字母：
        StringBuilder sb = new StringBuilder(rondomArr(arr));
        int number = r.nextInt(10);//0~9
        //获取拼接后的字母和数字：
        String str = rondomStr(sb.append(number).toString());

        return str;
    }
    //创造一个方法，打乱数组，将4位字母进行拼接
    public static String rondomArr(char[] arr){
        Random random = new Random();
        char[] newArr = new char[4];
        for (int i = 0; i < 4; i++) {
            int index = random.nextInt(arr.length);
            newArr[i] = arr[index];
        }
        //把字符数组转换为字符串，返回
        String newStr = new String(newArr);
        return newStr;

    }
    //创造一个方法，打乱拼接后的字母和数字
    public static String rondomStr(String str){
        char[] arr = new char[str.length()];

        Random r = new Random();
        //创造一个布尔数组，未被存入数据时布尔数组存的faluse
        boolean[]bl = new boolean[str.length()];

        //避免标记重复：
        for (int i = 0; i < str.length(); i++) {
            int index;
            do{
                //产生随机数字
                index = r.nextInt(str.length());//0~4
            }while(bl[index]);//刚开始布尔数组存的都是faluse，所以会跳出循环

            bl[index] = true;//标记为已使用

            //将打乱后的字母和数字放入字符数组中去
            arr [i] = str.charAt(index);
        }
        //最后将字符数组变为字符串：
        String stu = new String(arr);
        //返回字符串：
        return stu;
    }
    //构造一个方法，保证id（用户名）唯一
    public static boolean contains(String id, ArrayList<User> list) {
        return getId(list,id)!=-1;
    }
    //再构造一个方法,也可以保证ld（用户名）唯一
    public static int getId(ArrayList<User> list, String id) {
        for (int i = 0; i < list.size(); i++) {
            if(id.equals(list.get(i).getUsername()))
            {
                return i;
            }
        }
        return -1;
    }
    //重构一个方法，用来获取密码：
    public static int getPassword(ArrayList<User> list, String id) {
        for (int i = 0; i < list.size(); i++) {
            if(id.equals(list.get(i).getPassword()))
            {
                return i;
            }
        }
        return -1;
    }
    //这两个方法用来验证用户名的长度要求，以及用户名字符合法性，验证成功后返回
    //正确的用户名
    public static String getUsername(ArrayList<User> list) {
        Scanner sc = new Scanner(System.in);

        while (true) { // 添加循环重试机制
            //键盘录入用户名：
            String username = sc.next();
            //判断用户名是否唯一
            String Name = "";
            int result = getId(list,username);

            if(result == -1){ // 用户名不存在（可用）的情况
                // 先判断长度是否符合要求
                if(username.length()>=3 && username.length()<=15){
                    // 验证字符合法性
                    Name = correctUsername(list,username);
                    // 如果验证通过则返回
                    if (!Name.startsWith("用户名不符合要求")) {
                        return Name;
                    } else {
                        System.out.println(Name + "，请重新输入：");
                    }
                } else {
                    System.out.println("用户名长度必须在3-15之间，请重新输入：");
                }
            } else { // 用户名已存在的情况
                System.out.println("用户名已存在，请重新输入：");
            }
        }
    }
    public static String correctUsername(ArrayList<User> list, String username) {
        char[] allChars = new char[62];
        int index = 0;
        // 存储小写字母 a-z
        for (char c = 'a'; c <= 'z'; c++) {
            allChars[index++] = c;
        }
        // 存储大写字母 A-Z
        for (char c = 'A'; c <= 'Z'; c++) {
            allChars[index++] = c;
        }
        // 存储数字 0-9
        for (char c = '0'; c <= '9'; c++) {
            allChars[index++] = c;
        }

        // 检查所有字符是否都合法
        for (int i = 0; i < username.length(); i++) {
            boolean isValid = false;
            char currentChar = username.charAt(i);

            // 检查当前字符是否在合法字符数组中（包括所有字符，不再排除数字）
            for (int j = 0; j < allChars.length; j++) {
                if (allChars[j] == currentChar) {
                    isValid = true;
                    break;
                }
            }

            // 如果有任何字符不合法，直接返回错误信息
            if (!isValid) {
                return "用户名不符合要求：包含非法字符，只能使用字母和数字";
            }
        }
        // 在所有字符验证通过后添加
        int letterCount = 0;
        int digitCount = 0;
        for (int i = 0; i < username.length(); i++) {
            char c = username.charAt(i);
            if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z')) {
                letterCount++;
            } else if (c >= '0' && c <= '9') {
                digitCount++;
            }
        }

        // 如果全是数字则不允许
        if (letterCount == 0 && digitCount > 0) {
            return "用户名不符合要求：不能使用纯数字";
        }

        // 所有字符都合法
        return username;
    }
    //用来判断方法是否输入不一致
    public static boolean rightPassword(String pw1, String pw2) {

        if(pw1.equals(pw2)){
            //如果字符串一致，flag = true 说明符合要求
            return true;
        }
        //说明不符合要求，返回false
        return false;
    }
    //判断身份证的合法性：
    public static String rightIdCard(ArrayList<User> list, String idCard) {
        // 1. 先判断长度是否为18位
        if (idCard.length() != 18) {
            return "身份证不满足要求：长度必须为18位";
        }

        // 2. 校验前17位是否全为数字
        for (int i = 0; i < 17; i++) { // 明确遍历前17位（0-16索引）
            char c = idCard.charAt(i);
            if (c < '0' || c > '9') {
                return "身份证不满足要求：前17位必须为数字";
            }
        }

        // 3. 校验第18位（最后一位）：可以是数字或X/x
        char lastChar = idCard.charAt(17);
        if (!((lastChar >= '0' && lastChar <= '9') ||
                lastChar == 'X' || lastChar == 'x')) {
            return "身份证不满足要求：最后一位必须是数字或X/x";
        }

        // 4. 所有校验通过
        return idCard;
    }
    //判断手机号是否正确：
    public static String rightPhoneNumber(ArrayList<User> list, String phoneNumber) {
        if(phoneNumber.length()!=11){
            return"手机号输入不合法：长度不为11位";
        }
        if(phoneNumber.charAt(0)=='0'){
            return "手机号输入不合法：手机号以0为开头";
        }
        for (int i = 0; i < phoneNumber.length(); i++) {
            char c = phoneNumber.charAt(i);
            if (c < '0' || c > '9') {
                return "手机号输入不合法：手机号必须都为数字";
            }
        }
        return phoneNumber;
    }
}

